﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TrackSystem.Entities.Extensions;
using TrackSystem.IO.Alarm;
using TrackSystem.IO.Data;
using TrackSystem.IO.Models;

namespace TrackSystem.IO.Protocol
{
    /// <summary>
    /// DCDC电源板通信协议
    /// </summary>
    public class PowerProtocol : ProtocolBase
    {
        private int repeatTimes;    //写入操作重复次数
        private int startTicks;
        private int[] wReg;
        private bool bSendR, bSendW;     // 发送标志

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="name"></param>
        /// <param name="station"></param>
        public PowerProtocol(string name, int station) 
            : base()
        {
            Name = name;
            Station = station;
            NeedInit = false;

            wReg = new int[2];

            Tx_r = new byte[] { 0xFF, 0xFF, 0xA5, 0x61, 0x01, 0x05, 0xCC, 0x26 };
            Tx_w = new byte[] { 0xFF, 0xFF, 0xA5, 0x61, 0x02, 0x06, 0x00, 0xCC, 0x26 };
            Tx_r[3] = (byte)(Station + 0x60);
            Tx_r[6] = (byte)(Tx_r[3] + Tx_r[4] + Tx_r[5]);

            Tx_w[3] = Tx_r[3];

            bSendR = false;
            bSendW = false;
        }

        /// <summary>
        /// 生成读取寄存器的通讯帧
        /// </summary>
        /// <returns></returns>
        public override byte[] GenerateReadFrame(out int NeedRecvLen)
        {
            startTicks = Environment.TickCount;
            // 上次的发送没有收到正确回复，bSend没有被置位
            if (bSendR)
            {
                Fail_R++;
                Succ_R = 0;
            }
            bSendR = true;

            NeedRecvLen = 30;
            return Tx_r;
        }

        /// <summary>
        /// 根据收到的内容进行处理
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public override bool ProcessReadFrame(byte[] buffer)
        {
            Rx_r = buffer;
            Lapse = Environment.TickCount - startTicks;

            if (buffer[0] != 0xFF || buffer[1] != 0xFF || buffer[2] != 0xA5)
                return false;

            if (buffer[3] != Tx_r[3])
                return false;

            int ptr = 6;
            for(int i=0; i < 10; i++)
            {
                RegFactory.Instance.SetVal(RegNameList[i], buffer[ptr++] << 8 | buffer[ptr++]);
            }

            Succ_R++;
            bSendR = false;     // 正确收到，标志位变为false
            Fail_R = 0;         // 通信成功，则将失败次数清零
            return true;
        }


        /// <summary>
        /// 生成写入寄存器的通讯帧
        /// </summary>
        /// <param name="NeedRecvLen"></param>
        /// <returns></returns>
        public override byte[] GenerateWriteFrame(out int NeedRecvLen)
        {
            startTicks = Environment.TickCount;

            // 待写入的数据队列非空 
            if (writeQueue.Count() > 0)
            {
                while (writeQueue.TryDequeue(out AddressAndVal data))
                {
                    wReg[data.Address] = (int)data.Value;
                }
                repeatTimes = 3;    // 写入的重复次数更新为3次
            }

            if (WriteFlag && repeatTimes-- > 0)
            {
                // 上次没有收到正确的返回帧
                if (bSendW)
                {
                    Fail_W++;
                    Succ_W = 0;
                }
                bSendW = true;

                NeedRecvLen = 11;
                Tx_w[6] = (byte)((wReg[0] == 0) ? 0 : 1);
                if (wReg[1] != 0)
                    Tx_w[6] |= 0x10;
                Tx_w[7] = (byte)(Tx_w[3] + Tx_w[4] + Tx_w[5] + Tx_w[6]);

                return Tx_w;
            }

            // 如果写入次数超过三次未成功，则将队列清空
            if (repeatTimes <= 0)
            {
                AlarmFactory.Instance.Insert("Write data error, more than three attempts",
                    AlarmCategory.COMM, Name, 0);
                WriteFlag = false;
            }

            NeedRecvLen = 0;
            return null;
        }

        /// <summary>
        /// 根据收到的内容进行处理
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public override bool ProcessWriteFrame(byte[] buffer)
        {
            Lapse = Environment.TickCount - startTicks;
            Rx_w = buffer;

            //帧格式不正确
            if (buffer[0] != 0xFF || buffer[1] != 0xFF || buffer[2] != 0xA5)
                return false;

            //站号判断
            if (buffer[3] != Tx_w[3])
                return false;

            Succ_W++;
            bSendW = false;
            Fail_W = 0;  // 通信成功，则将失败次数清零

            WriteFlag = false;  //上次的写数据成功
            repeatTimes = 0;

            return true;
        }

        /// <summary>
        /// 改变变量的值
        /// </summary>
        /// <param name="Index"></param>
        /// <param name="Value"></param>
        public override void PushRegValue(int Index, double Value)
        {
            if (Index == 0 || Index == 1)
            {
                writeQueue.Enqueue(new AddressAndVal(Index, Value));
                WriteFlag = true;
            }
        }
    }
}
